<?php

namespace App\Modules\Apicrzs\Services;


use App\Exceptions\Exception;
use App\Library\SMS\aliyunsdk\AliyunSms;
use App\Library\SMS\AliYunService;
use App\Modules\Apicrzs\Entities\UsersModel;
use App\Modules\Apicrzs\Http\Requests\RetrieveRequest;
use App\Modules\Apicrzs\Services\Tools\SmsService;
use App\Traits\CryptAES;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class LoginService extends BaseServices
{


    public function __construct(UsersModel $model)
    {
        $this->model = $model;
    }
    /**
     *账号登陆
     */
    public function login($request)
    {
        $account = $request->input('account');
        $password = $request->input('password');
        $spread = $request->input('spread');
        $user_info = $this->model->where('username',$account)->first();
        if(empty($user_info)){
            $this->error='账号或密码错误';
            return false;
        }
        $salt= $user_info['salt'];
        $hashedPassword = md5($password.$salt);

        // 验证密码

        $hashedPasswordFromDb = $user_info['password'];
        if ($hashedPassword!=$hashedPasswordFromDb) {
            // 密码匹配
            $this->error='账号或密码错误';
            return false;
        }
        if ($user_info['flag']==-1){
            $this->error='当前账户已封号，请联系客服！';
            return false;
        }
        $token = CryptAES::createToken([
            'user_id' => $user_info['id'],
            'nickname' => $user_info['nickname'],
            'mobile' => $user_info['mobile'],
            'water_role' => $user_info['water_role'],
            'salt' => rand_str(),
        ],'user_grzq');

        $exp_time = strtotime('+ 30day');



        $this->update(['id'=>$user_info['id'],'last_time'=>time(),'last_ip'=>get_ip()]);
        return  ['token' =>  $token,'uid' =>  $user_info['id'], 'expires_time' => $exp_time,'user_info'=>$user_info];
    }

    /**
     *  获取验证码
     * @param $params
     * @return array|false
     */
    public function getVerifyCode($params){
        $phone = $params['phone'];
        if (!is_mobile($phone)) {
            $this->error='手机号格式不正确';
            return false;
        }
        $type = $params['type']=='reset'?"register":$params['type']??"register";
        $key = $params['key'];
        if (!$phone){
            return false;
        }
        if ($type == 'register'){
            $userlist = $this->model->where('username',$phone)->get();
            if (count($userlist)){
                $this->error='此手机号已注册';
                return false;
            }
        }
        $keyName = 'sms.key.' . $key;
        if (!Cache::has($keyName)) {
            $this->error = '发送验证码失败,请刷新页面重新获取';
            return false;
        }
        // 验证限制
        // 验证码每分钟发送上限
        $maxMinuteCountKey = 'sms.minute.' . $phone . date('YmdHi');
        $minuteCount = 0;
        $maxMinuteCount = 1;

        if (Cache::has($maxMinuteCountKey)) {
            $minuteCount = Cache::get($maxMinuteCountKey);
            if ($minuteCount > $maxMinuteCount) {
                $this->error = "同一手机号每分钟最多发送"+$maxMinuteCount+"条";
                return false;
            }
        }

        // 验证码单个手机每日发送上限
        $maxPhoneCountKey = 'sms.phone.' . $phone . '.' . date('Ymd');
        $phoneCount = 0;
        $maxPhoneCount = 5;
        if (Cache::has($maxPhoneCountKey)){
            $phoneCount = Cache::get($maxPhoneCountKey);
            if ($phoneCount > $maxPhoneCount) {
                $this->error = "同一手机号每天最多发送" + $maxPhoneCount + "条";
                return false;
            }
        }

        // 验证码单个手机每日发送上限
        $maxIpCountKey = 'sms.ip.' . app()->request->ip() . '.' . date('Ymd');
        $ipCount = 0;
        $maxIpCount = 5;
        if (Cache::has($maxIpCountKey)){
            $ipCount = Cache::get($maxPhoneCountKey);
            if ($ipCount > $maxIpCount) {
                $this->error = '同一手机号每天最多发送' . $maxPhoneCount . '条';
                return false;
            }
        }

        $time = time();
        $code = rand(100000, 999999);
        //SmsService::send($phone,$code,$type);
        $sms = new AliyunSms();
        $sms->sms_send($phone,$code,$type);

        Cache::set('code_' . $phone, $code, $time * 60);
        Cache::set($maxMinuteCountKey, $minuteCount + 1, 61);
        Cache::set($maxPhoneCountKey, $phoneCount + 1, 86401);
        Cache::set($maxIpCountKey, $ipCount + 1, 86401);
       return ['code'=>$code];

    }

    /**
     * @param $params
     * @return false
     */
    public function register($params)
    {
        $openid = $params['openid'];
        $account = trim($params['account']);
        $captcha = $params['captcha'];
        $password = trim($params['password']??'123456');
        $verifyCode = Cache::get('code_' . $account);

        $verifyCode = substr($verifyCode, 0, 6);
        if ($verifyCode != $captcha) {
            $this->error = '验证码错误！';
            return false;
        }
        if($openid){
            $user_info = $this->model->where(['openid'=>$openid])->first();
        }else{
            $user_info = $this->model->where(['mobile'=>$account])->first();
        }
        $salt=rand_str();
        $nickname = "甄泉".$account;
        $hashedPassword = md5($password.$salt);
        $insert_array['username'] = $account;
        $insert_array['nickname'] = $nickname;
        $insert_array['password'] = $hashedPassword;
        $insert_array['pw'] = $password;
        $insert_array['salt'] = $salt;
        $insert_array['mobile'] = $account;
        $insert_array['water_role'] = "intake";
        $insert_array['last_time'] = time();
        $insert_array['last_ip'] = get_ip();
        DB::beginTransaction();
        try{
            if ($user_info){
                $insert_array['id'] = $user_info['id'];
                $this->detail = parent::update($insert_array);
            }else{
                $insert_array['openid'] = $openid;
                $this->detail = parent::create($insert_array); // TODO: Change the autogenerated stub
            }
            $token =CryptAES::createToken(
                [
                    'user_id' => $this->detail['id'],
                    'nickname' =>  $this->detail['nickname'],
                    'mobile' => $this->detail['mobile'],
                    'water_role' => "intake",
            ],'user_grzq');
            DB::commit();
            Cache::delete('code_' . $account);
            $exp_time = strtotime('+ 30day');
            return  ['token' =>  $token,'uid' =>  $this->detail['id'], 'expires_time' => $exp_time,'user_info'=>$this->detail];
        }catch (Exception $e){
            DB::rollBack();
            $this->error='请求失败';
            return false;
        }
    }

    /***
     *  找回密码
     * @param $params
     * @return bool
     */
    public function retrieve($params){
        $phone = $params['phone']??"";
        $password = $params['password']??"";
        $captcha = $params['captcha']??"";

        if (empty($phone)) {
            $this->error='请填写手机号！';
            return false;
        }
        if (empty($password)) {
            $this->error='请填写密码！';
            return false;
        }
        $user_info = $this->model->where('username',$phone)->first();

        if (empty($user_info)){
            $this->error='当前手机号不存在！';
            return false;
        }
        if (strlen(trim($password)) < 6 || strlen(trim($password)) > 32) {
            $this->error='账号密码必须是在6到32位之间';
            return false;
        }
        if ($password == '123456') {
            $this->error = '密码太过简单，请输入较为复杂的密码';
            return false;
        }
        $verifyCode = Cache::get('code_' . $phone);

        $verifyCode = substr($verifyCode, 0, 6);
        if ($verifyCode != $captcha) {
            $this->error = '验证码错误！';
            return false;
        }
        $hashedPassword = md5($password.$user_info['salt']);
        $res = $this->update(['id'=>$user_info['id'],'password'=>$hashedPassword,'pw'=>$password,'last_time'=>time(),'last_ip'=>get_ip()]);
       if ($res){
           Cache::delete('code_' . $phone);
           return true;
       }else {
           $this->error='找回密码失败';
           return false;
       }
    }




}
